import java.util.HashSet;
import java.util.Set;

/**
 * Created by L.jp
 * Description:给定一个包含n + 1 个整数的数组nums ，其数字都在 1 到 n之间（包括 1 和 n），可知至少存在一个重复的整数。
 *
 * 假设 nums 只有 一个重复的整数 ，找出 这个重复的数 。
 *
 * 你设计的解决方案必须不修改数组 nums 且只用常量级 O(1) 的额外空间。
 * 示例 ：
 *
 * 输入：nums = [3,1,3,4,2]
 * 输出：3

 * User: 86189
 * Date: 2021-11-03
 * Time: 21:47
 */
public class FindDuplicates {
    public static int findDuplicate(int[] nums) {
        //集合的方法
        /*
        Set<Integer> set=new HashSet<>();
        int tmp=0;
        for(int n:nums){
            if(set.contains(n)){
                tmp=n;
            }
            set.add(n);
        }
        return tmp;

         */
       //二分查找法，抽屉法，思想：如果小于等于4的个数大于4本身，那么这个重复的数就在1~4之间(看成是下标），首先定义left和right指针位于0和n-1下标
        //所以当小于等于mid的个数大于mid时，重复数就在1~mid之间;当个数小于mid时，重复数在mid~right之间;不断找mid,直到left和right相遇
        int  left=1;//重复数一定在1~n之间
        int right= nums.length-1;
        while(left<right){
            int mid=left+(right-left)/2;
            int count=0;
            for(int i=0;i< nums.length;i++){
                if(nums[i]<=mid){
                    count++;
                }
            }
            if(count<mid){
                left=mid+1;
            }else{
                right=mid;//重复数就在1~mid之间
            }
        }
        return left;//left和right相遇，返回left就是重复数
    }



    public static void main(String[] args) {
        int []nums={3,1,3,4,2};
        System.out.println(findDuplicate(nums));
    }

}
